package com.jysz.certificate.web.action.mf;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jysz.certificate.action.AbstractBaseAction;
import com.jysz.certificate.persistence.enums.mf.BillStatus;
import com.jysz.certificate.persistence.model.mf.Bill;
import com.jysz.certificate.persistence.model.mf.BillApply;
import com.jysz.certificate.persistence.model.mf.BillOption;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.Shop;
import com.jysz.certificate.persistence.model.system.Treaty;
import com.jysz.certificate.service.cm.CertificationService;
import com.jysz.certificate.service.mf.BillApplyService;
import com.jysz.certificate.service.mf.BillOptionService;
import com.jysz.certificate.service.mf.BillService;
import com.jysz.certificate.service.system.FinancialService;
import com.jysz.certificate.service.system.ShopService;
import com.jysz.certificate.service.system.TreatyService;
import com.jysz.certificate.utils.CommonUtil;
import com.jysz.certificate.utils.DateUtil;
import com.jysz.certificate.utils.PoiUtils;
import com.jysz.webcore.ssh.orm.hibernate.support.Page;

/**
 * 发票申请控制类(申请列表、申请-店)
 * @author xuxiaolong
 */
@Controller
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Namespace("/mf/apply")
public class BillApplyFinancialAction extends AbstractBaseAction {

	private static final long serialVersionUID = -3011627853588411366L;

	@Resource
	private BillApplyService applyService;
	@Resource
	private BillOptionService optionService;
	@Resource
	private TreatyService treatyService;
	@Resource
	private ShopService shopService;
	@Resource
	private BillService billService;
	@Resource
	private FinancialService financialService;
	@Resource
	private CertificationService cfService;
	
	@Resource
	private BillOptionService billOptionService;
	
	private BillApply entity;
	private BillApply search;
	private Bill bill;
	private Long id;
	private Long billOpenId;
	private Long shopId;
	private Long billId;
	private Long applyId;
	private String shopName;
	private String remark;
	private String month;
	private double amount;
	private Shop shop;
	private Shop shopDTO;
	public String getMonth() {
		return month;
	}

	public void setMonth(String month) {
		this.month = month;
	}

	public Long getBillId() {
		return billId;
	}

	public void setBillId(Long billId) {
		this.billId = billId;
	}

	public Shop getShopDTO() {
		return shopDTO;
	}

	public void setShopDTO(Shop shopDTO) {
		this.shopDTO = shopDTO;
	}

	public Shop getShop() {
		return shop;
	}

	public void setShop(Shop shop) {
		this.shop = shop;
	}

	private BillOption billOption;
	
	public String getShopName() {
		return shopName;
	}

	public void setShopName(String shopName) {
		this.shopName = shopName;
	}

	private Long financialId;
	private List<Object[]> detailData;//发票申请单详情所需列表
	private List<Financial> financials;//允许预收的金融机构
	private String editData;//存放编辑发票时表格中原有行的数据
	private String newData;//存放编辑发票时表格中新增行的数据
	private String months;//编辑发票时新增的月份
	
	//提交发票
			@Action("billSubmit")
			public String billSubmit(){
				BillApply billApply = applyService.find(applyId);
				billApply.setApplyDate(new Date());
				List<Bill> delBills=new ArrayList<Bill>();
				for(int j=0;j<billApply.getBills().size();j++){
					bill = billApply.getBills().get(j);
					Map<String, String> monthsMap = new HashMap<String, String>();//记录当前金融机构的开票月份
					String monthsReams = "";
					if(bill.getStatus().compareTo(BillStatus.TEMPSAVE) == 0){
						if(bill.getReceivableAmount() > 0){
							bill.setStatus(BillStatus.APPLYED);
						}else{
							bill.setBillNum("系统默认开票");
							bill.setBillName("系统默认开票");
							bill.setOpenDate(new Date());
							bill.setStatus(BillStatus.OPENED);
						}
						
						for(int i=0;i<bill.getOptions().size();i++){
							BillOption billOption = bill.getOptions().get(i);
							if(billOption.getAmount() >0){
								billOption.setStatus(BillStatus.APPLYED);
							}else{
								billOption.setStatus(BillStatus.OPENED);
							}
							if(!monthsMap.containsKey(billOption.getMonth())){
								monthsMap.put(billOption.getMonth(), billOption.getMonth());
								String m = billOption.getMonth().substring(5, 7) + "月";
								monthsReams = monthsReams+" "+m;
							}
							
							billOptionService.save(billOption);
						}
						bill.setBillRemark(bill.getFinancial().getBrief()+":"+monthsReams+" "+bill.getReceivableAmount());
						if(bill.getOptions().size()>=1){
							billService.save(bill);
						}else{
							
//							billService.destory(bill.getId());
							delBills.add(bill);
						}
						
					}
				}
				if(delBills.size()>0){
					for(Bill b:delBills){
						b.setBillApply(null);
						billApply.getBills().remove(b);
						billService.destory(b);
					}
				}
				billApply.setStatus(BillStatus.APPLYED);
//				billApply.setShopFlag(false);
				if(billApply.getBills().size()>=1){
					applyService.save(billApply);
					setSuccessPopMessage("申请开票成功");
				}else{
					applyService.destory(billApply);
					setSuccessPopMessage("没有可开发票明细，申请单系统默认删除");
				}
				
				setRedirectUrl("index.do?currentPage="+getCurrentPage(),"search",search);
				return SHOW_MSG_PAGE;
			}
	
	//新建发票申请--金融机构
	@Action("addFinancial")
	public String addFinancial(){
		try {
			Object flag=this.getServletContext().getAttribute("MfApplyFinInProgress");//检测是否有正在生成
			if(flag!=null&&flag.toString().equals("1")){
				setFailPopMessage("上一次生成还在进行中，请稍后重试");
			}else{
				this.getServletContext().setAttribute("MfApplyFinInProgress","1");//设置正在生成标识,不允许其他
				entity = applyService.createFinancial(getUser());
				if(null == entity){
					setRedirectUrl("index.do?currentPage="+getCurrentPage(),"search",search);
					setSuccessPopMessage("没有可以开立的发票");
					setRedirectUrl("index.do?currentPage="+getCurrentPage(),"search",search);
					return SHOW_MSG_PAGE;
				}
				detailData=applyService.view(entity.getId());
				setSuccessPopMessage("已成功生成所有应收管理费");
				setRedirectUrl("index.do?currentPage="+getCurrentPage(),"search",search);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}finally{
			this.getServletContext().removeAttribute("MfApplyFinInProgress");//去掉正在生成标识
		}
		//setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return SHOW_MSG_PAGE;
	}
	//发票申请编辑--金融机构
	@Action("editFinancial")
	public String editFinancial(){
		entity = applyService.find(entity.getId());
		
		//setPage(applyService.findPage(search, getCurrentPage(), getPageSize()));
		return "billApplyFinancialEdit";
	}
	//发票编辑
	@Action("billFinancialEdit")
	public String billFinancialEdit(){
		bill = billService.find(id);
		Page<BillOption> page = billOptionService.billOptionFinadPage(id, shopName, this.getCurrentPage(), this.getPageSize());
		// 查询看是否有当前月份被之前预收的。也作显示
		List<BillOption> options = applyService.findCurrentMonthAdvance(bill.getFinancial().getId(), DateUtil.formatDate(new Date(), "yyyy-MM"),bill.getId());
		if(options!=null){
			for(BillOption bo:options){
					bo.setOperate(2);
					page.getResult().add(bo);
			}
		}
		setPage(page);
		return "billFinancialEdit";
		}
	//发票编辑详情
		@Action("billFinaOptionUpdate")
		public String billFinaOptionUpdate(){
			billOption = billOptionService.find(billOpenId);
			id=getId();
			return "updatebillFinancial";
			}
		
		/**
		 * 发票申请单详情
		 * @return
		 */
		@Action("viewFinad")
		public String viewFinad(){
			entity = applyService.find(id);
			return "billApplyFinancialView";
		}
		/**
		 * 发票申请单详情
		 * @return
		 */
		@Action("billFinancialView")
		public String billFinancialView(){
			bill=billService.find(id);
//			entity = applyService.find(id);
			Page<BillOption> page=billOptionService.billOptionFinadPage(id, shopName, this.getCurrentPage(), this.getPageSize());
			// 查询看是否有当前月份被之前预收的。也作显示
			List<BillOption> options=applyService.findCurrentMonthAdvance(bill.getFinancial().getId(),DateUtil.formatDate(new Date(), "yyyy-MM"),bill.getId());
			if(options!=null){
				for(BillOption bo:options){
						bo.setOperate(2);
						page.getResult().add(bo);
				}
			}
			setPage(page);
			return "billFinancialView";
		}
		
		//发票-详情(用作显示关联的其它发票)
		@Action("billDisplayFin")
		public String billDisplayFin(){
			
			BillOption option=optionService.find(id);
			if(option!=null&&option.getBills()!=null&&option.getBills().size()>0){
				bill=option.getBills().get(0);
				setPage(billOptionService.billOptionFinadPage(bill.getId(), shopName, this.getCurrentPage(), this.getPageSize()));
			}
			
			
			return "billFinancialView";
		}
	
		@Action("billOptionUpdate")
		public String billOptionUpdate(){
			billOption = billOptionService.find(billOpenId);
			bill = billService.find(id);
			bill.setReceivableAmount(bill.getReceivableAmount()-billOption.getAmount()+amount);
			if(amount<billOption.getAmount())
				billOption.setLessThan(1);
			else
				billOption.setLessThan(0);
			billOption.setAmount(amount);
			billOption.setRemark(remark);
			billOptionService.save(billOption);
			billService.save(bill);
//			id = billOption.getBill().getId();
			return this.billFinancialEdit();
			}
		@Action("addbillFinal")
		public String addbillFinal(){
			bill=billService.find(billId);
			return "addbillFinancial";
		}
		
		@Action("selectShop")
		public String selectShop(){//aaaaaaaaaaaaaaaa----------------------------选择店需要修改
				setPage(shopService.applyShop(shopDTO, financialId, getCurrentPage(), getPageSize()));
			return "selectShop";
		}
		
		@Action("addBillOpention")
		public String addBillOpention(){
			bill = billService.find(id);
			List<Bill> bills =new ArrayList<Bill>();
			bills.add(bill);
			billOption.setStatus(BillStatus.TEMPSAVE);
			billOption.setFinancial(bill.getFinancial());
			String defendName =applyService.findUserShopByShopName(billOption.getShop().getId());//获得驻店员的名字
			String managerName =applyService.findUserDomainByShopName(billOption.getShop().getId());//获得区域经理的名字
			int  moneyStock = cfService.findCertificationInMonthBill(billOption.getFinancial().getId(),billOption.getShop().getId(),billOption.getMonth());//获得指定日期内的入库数
			int  moneyRemain = cfService.findBeforeCertifcatiionInQtyBill(billOption.getFinancial().getId(),billOption.getShop().getId(),billOption.getMonth());//获得指定日期内的结存数
			int  quantity = applyService.findReleaseCertificationInMonth(billOption.getFinancial().getId(),billOption.getShop().getId(),billOption.getMonth());//获得指定日期内的释放数
			Treaty treaty=treatyService.find(billOption.getFinancial().getId(),billOption.getShop().getId());
			if(billOption.getAmount()<treaty.getFloors())
				billOption.setLessThan(1);
			else
				billOption.setLessThan(0);
			billOption.setDefendName(defendName);
			billOption.setMoneyRemain(moneyRemain);
			billOption.setMoneyStock(moneyStock);
			billOption.setManagerName(managerName);
			billOption.setQuantity(quantity);
			billOption.setOperate(0);
			billOption.setTreaty(treaty);//添加相关的协议
			billOption.setAdvance(true);
			billOptionService.save(billOption);
			bill.getOptions().add(billOption);
//			billOption.setBills(bills);
			bill.setReceivableAmount(billOption.getAmount()+bill.getReceivableAmount());
//			billOptionService.save(billOption);
			billService.save(bill);
			setRedirectUrl("billFinancialEdit.do?currentPage="+getCurrentPage()+"&id="+id,null,id);
			setSuccessPopMessage("预收管理费成功");
			return SHOW_MSG_PAGE;
		}
		@Action("keyBillOpention")
		public String keyBillOpention(){
			boolean bo =billOptionService.keyBillOpention(shopId, month,financialId);
			Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
			if(bo){
				
				this.setJsonText(gson.toJson("该月份不可重复收费"));
			}else{
				this.setJsonText(gson.toJson("null"));
			}
			return JSON_PAGE;
		}
	


	
	/** 统计一个发票申请 所包含的金额总和*/
	public Double getSumAmount(Long id){
		BillApply tmp= applyService.find(id);
		BigDecimal big=new BigDecimal(0D);
		for(Bill bill:tmp.getBills()){
			big.add(new BigDecimal(bill.getReceivableAmount()));
		}
		return big.doubleValue();
	}
	
	/**
	 * 获得预收的下一个月
	 * @return
	 * @throws Exception
	 */
	@Action("findNextMonth")
    public String findNextMonth() throws Exception {  
       // months=financialId=shopId="";
        List<String> monthList=applyService.findAdvanceMonths(financialId, shopId);
        if(CommonUtil.isNotEmpty(months)){
        	String ary[]=months.split(",");
        	for(String m:ary){
        		monthList.add(m);
        	}
        }
        String m=getNextMonth(monthList);
        Treaty t=treatyService.find(financialId, shopId);
        Double d=0D;
        if(t!=null)
        	d=t.getFloors();
        setJsonMsg("", true, d+"_"+m);
          
        return JSON_PAGE;  
    }
	
	/**
	 * 检查是否重复
	 * @return
	 * @throws Exception
	 */
	@Action("checkMonth")
	public String checkMonth() throws Exception {  
		// months=financialId=shopId="";
		int count=applyService.checkMonth(financialId, shopId,months);
		setJsonMsg("", count>0?true:false, null);
		
		return JSON_PAGE;  
	}
	
	/**
	 * 删除发票明细
	 * @return
	 * @throws Exception
	 */
	@Action("delBillOption")
	public String delBillOption() throws Exception {  
		// months=financialId=shopId="";
		applyService.delBillOption(id);
		setJsonMsg("", true, null);
		
		return JSON_PAGE;  
	}
	@Action("exportBillOpen")
	public String exportBillOpen(){
		List<BillOption> billOptions = billOptionService.exportBillOptions(id);
		String[] headers = {"代号", "销售店名称","驻店顾问","区域经理", "管理期间","本月入库","上月结存", "当月释放合格证数量(张)", "应收管理费(元)"};
		String[] columns = {"shop.shopMark", "shop.shopName","defendName","managerName", "month","moneyStock","moneyRemain", "quantity", "amount"};
		HttpServletResponse response = this.getResponse();
	    response.setContentType("octets/stream");
	    response.addHeader("Content-Disposition","attachment;filename=" + toUtf8Encode("金融机构发票明细") + ".xls");
	    OutputStream out = null;
		try {
			out = this.getResponse().getOutputStream();
			Map<String, Object> context = new HashMap<String, Object>();
			context.put("cfa", this);
			PoiUtils.exportExcel("金融机构发票明细", headers, columns, billOptions, out, null, context);
		} catch (Exception e) {
			LOG.error("导出金融机构发票明细出错。。。", e);
		}
		
		return null;
	}
	
	private String getNextMonth(List<String>list) throws ParseException{
		if(list==null||list.size()==0){
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
			return DateUtil.getNextMonth(sdf.format(new Date()));
		}
		List<String> l=new ArrayList<String>(new LinkedHashSet<String>(list));
		Collections.sort(l);
		
		String rus=null,tmp=null;
		int length=l.size();
		for(int i=0;i<length;i++){
			if(i==length-1)
				rus=DateUtil.getNextMonth(l.get(i));
			else{
				tmp=DateUtil.getNextMonth(l.get(i));
				if(tmp.equals(l.get(i+1)))
					continue;
				else{
					rus=tmp;
					break;
				}
					
			}
		}
		return rus;
	}
	
	
	public BillApply getEntity() {
		return entity;
	}

	public void setEntity(BillApply entity) {
		this.entity = entity;
	}

	public BillApply getSearch() {
		return search;
	}

	public void setSearch(BillApply search) {
		this.search = search;
	}

	public List<Object[]> getDetailData() {
		return detailData;
	}

	public void setDetailData(List<Object[]> detailData) {
		this.detailData = detailData;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Bill getBill() {
		return bill;
	}

	public void setBill(Bill bill) {
		this.bill = bill;
	}

	public List<Financial> getFinancials() {
		return financials;
	}

	public void setFinancials(List<Financial> financials) {
		this.financials = financials;
	}

	public String getMonths() {
		return months;
	}

	public void setMonths(String months) {
		this.months = months;
	}

	public Long getShopId() {
		return shopId;
	}

	public void setShopId(Long shopId) {
		this.shopId = shopId;
	}

	public Long getFinancialId() {
		return financialId;
	}

	public void setFinancialId(Long financialId) {
		this.financialId = financialId;
	}

	public String getEditData() {
		return editData;
	}

	public void setEditData(String editData) {
		this.editData = editData;
	}

	public String getNewData() {
		return newData;
	}

	public void setNewData(String newData) {
		this.newData = newData;
	}

	public Long getBillOpenId() {
		return billOpenId;
	}

	public void setBillOpenId(Long billOpenId) {
		this.billOpenId = billOpenId;
	}

	public BillOption getBillOption() {
		return billOption;
	}

	public void setBillOption(BillOption billOption) {
		this.billOption = billOption;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public double getAmount() {
		return amount;
	}

	public void setAmount(double amount) {
		this.amount = amount;
	}

	public Long getApplyId() {
		return applyId;
	}

	public void setApplyId(Long applyId) {
		this.applyId = applyId;
	}

	@Action(DESTORY)
	public String destory(){
		bill = billService.find(id);
		billService.del(bill);
//		applyService.delBillOptions(bill.getOptions());
		setSuccessPopMessage("删除数据成功");
		setRedirectUrl("editFinancial.do?entity.id=" + bill.getBillApply().getId());
		
		return SHOW_MSG_PAGE;
	}
}
